package com.thiswhyme.redis.lock.spel;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.expression.EvaluationContext;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * SpEL表达式工具
 *
 * @author thiswhyme
 * @date 2022/10/26
 */
public abstract class ExpressionUtils {

    private static final ExpressionEvaluator EVALUATOR = new ExpressionEvaluator();

    /**
     * 解析Key
     *
     * @param joinPoint
     * @param keyExpression
     * @return
     */
    public static String genKey(JoinPoint joinPoint, String keyExpression) {
        return genKey(joinPoint.getTarget(), joinPoint.getArgs(), joinPoint.getTarget().getClass(),
                ((MethodSignature) joinPoint.getSignature()).getMethod(), keyExpression);
    }

    /**
     * 解析KEY
     *
     * @param target
     * @param args
     * @param targetClass
     * @param method
     * @param keyExpression
     * @return
     */
    private static String genKey(Object target, Object[] args, Class<?> targetClass, Method method,
                                 String keyExpression) {
        if (!StringUtils.hasText(keyExpression)) {
            return "";
        }
        EvaluationContext evaluationContext = EVALUATOR.createEvaluationContext(method, args, targetClass, target);
        AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
        return EVALUATOR.key(keyExpression, methodKey, evaluationContext, String.class);
    }
}
